

namespace Stee.CAP8.MessageBus.Interfaces.Interfaces
{
    using System;
    using Stee.CAP8.MessageBus.Interfaces.Delegates;
    using Stee.CAP8.MessageBus.Interfaces.Enums;
    using Stee.CAP8.MessageBus.Interfaces.Models;

    /// <summary>
    /// Subscriber interface
    /// </summary>
    public interface ISubscriber : IDisposable
    {
        #region Properties

        /// <summary>
        /// Gets the message topic
        /// </summary>
        TopicName TopicName { get; }

        /// <summary>
        /// Gets the subscriber group ID
        /// </summary>
        string GroupID { get; }

        /// <summary>
        /// Gets the subscriber client ID
        /// </summary>
        string ClientID { get; }

        /// <summary>
        /// Gets the flag indicating that subscriber is initialized and ready for reading messages
        /// </summary>
        bool IsInitialized { get; }

        /// <summary>
        /// Gets the flag indicating if subscriber is polling for new messages
        /// </summary>
        bool IsConnected { get; }

        /// <summary>
        /// Gets the flag indicating disposed state
        /// </summary>
        bool IsDisposed { get; }

        #endregion Properties


        /// <summary>
        /// Initializes the subscription
        /// </summary>
        /// <param name="brokerConfigurationJSON">JSON configuration path</param>
        /// <param name="groupID">Subscriber group ID</param>
        /// <param name="topicName">Subscription topic</param>
        /// <param name="brokerErrorHandler">Broker error handler</param>
        /// <returns>Return TRUE if initialized else FALSE</returns>
        bool InitializeGeneric(string brokerConfigurationJSON, string groupID, TopicName topicName, HandleBrokerError brokerErrorHandler);

        /// <summary>
        /// Initializes the subscription
        /// </summary>
        /// <param name="brokerConfigurationJSON">JSON configuration path</param>
        /// <param name="groupID">Subscriber group ID</param>
        /// <param name="topicName">Subscription topic</param>
        /// <param name="brokerErrorHandler">Broker error handler</param>
        /// <returns>Return TRUE if initialized else FALSE</returns>
        bool InitializeEvent(string brokerConfigurationJSON, string groupID, TopicName topicName, HandleBrokerError brokerErrorHandler);

        /// <summary>
        /// Initializes the subscription
        /// </summary>
        /// <param name="brokerConfigurationJSON">JSON configuration path</param>
        /// <param name="groupID">Subscriber group ID</param>
        /// <param name="topicName">Subscription topic</param>
        /// <param name="brokerErrorHandler">Broker error handler</param>
        /// <returns>Return TRUE if initialized else FALSE</returns>
        bool InitializeCommand(string brokerConfigurationJSON, string groupID, TopicName topicName, HandleBrokerError brokerErrorHandler);

        /// <summary>
        /// Subscribe to configured topic
        /// </summary>
        /// <param name="subscribeMessageHandler">Subscribe message handler</param>
        void Subscribe(HandleSubscribe<GenericMessage> subscribeMessageHandler);

        /// <summary>
        /// Subscribe to configured topic
        /// </summary>
        /// <param name="subscribeEventHandler">Subscribe event handler</param>
        /// <param name="handlerPriority">Subscribe handler priority</param>
        /// <param name="isHandlerAsync">Flag indicating handler to process asynchronously</param>
        void Subscribe(HandleSubscribe<EventMessage> subscribeEventHandler, PriorityLevel handlerPriority, bool isHandlerAsync);

        /// <summary>
        /// Subscribe to configured topic
        /// </summary>
        /// <param name="subscribeCommandHandler">Subscribe command handler</param>
        void Subscribe(HandleSubscribe<CommandMessage> subscribeCommandHandler);

        /// <summary>
        /// Subscribe to configured topic
        /// </summary>
        /// <param name="subscribeCommandHandler">Subscribe command handler</param>
        /// <param name="actionName">Action name</param>
        void Subscribe(HandleSubscribe<CommandMessage> subscribeCommandHandler, string actionName);

        /// <summary>
        /// Unsubscribe from configured topic
        /// </summary>
        /// <param name="subscribeMessageHandler">Subscribe message handler</param>
        void Unsubscribe(HandleSubscribe<GenericMessage> subscribeMessageHandler);

        /// <summary>
        /// Unsubscribe from configured topic
        /// </summary>
        /// <param name="subscribeEventHandler">Subscribe event handler</param>
        /// <param name="handlerPriority">Subscribe handler priority</param>
        /// <param name="isHandlerAsync">Flag indicating handler to process asynchronously</param>
        void Unsubscribe(HandleSubscribe<EventMessage> subscribeEventHandler, PriorityLevel handlerPriority, bool isHandlerAsync);

        /// <summary>
        /// Unsubscribe from configured topic
        /// </summary>
        /// <param name="subscribeCommandHandler">Subscribed command handler</param>
        void Unsubscribe(HandleSubscribe<CommandMessage> subscribeCommandHandler);

        /// <summary>
        /// Unsubscribe from configured topic
        /// </summary>
        /// <param name="subscribeCommandHandler">Subscribed command handler</param>
        /// <param name="actionName">Action name</param>
        void Unsubscribe(HandleSubscribe<CommandMessage> subscribeCommandHandler, string actionName);

        /// <summary>
        /// Commit message
        /// </summary>
        /// <param name="brokerMessage">Raw broker message returned from subscription</param>
        /// <returns>Return TRUE if committed els FALSE</returns>
        bool Commit(object brokerMessage);

        ////// Note: This 'commit' interface is simpler but not recommeded as this interface is used by other message brokers besides Kafka
        //bool Commit(string topic, int partition, long offset)

        ///// <summary>
        ///// https://github.com/confluentinc/confluent-kafka-dotnet/issues/926, Describing group is not supported yet.
        ///// Reset consumer group offset to latest
        ///// </summary>
        ///// <param name="topicName">Subscription topic</param>
        ///// <returns>Return TRUE if the reset is successful else FALSE</returns>
        //bool ResetOffsetToLatest(TopicName topicName)
    }
}
